/*
 * 
 * 
 * 
 */
package com.hboxs.asl.entity;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.hboxs.asl.util.FreemarkerUtils;
import freemarker.template.TemplateException;
import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;

import javax.persistence.*;
import javax.validation.Valid;
import javax.validation.constraints.Digits;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * Entity - 促销
 */
@Entity
@Table(name = "xx_promotion")
@SequenceGenerator(name = "sequenceGenerator", sequenceName = "xx_promotion_sequence")
public class Promotion extends OrderEntity {

    private static final long serialVersionUID = 3536993535267962279L;


    /**
     * 访问路径前缀
     */
    private static final String PATH_PREFIX = "/promotion/content";

    /**
     * 访问路径后缀
     */
    private static final String PATH_SUFFIX = ".htm";

    /**
     * 促销类型
     */
    public enum Type {

        //免运费
        freeShipping,

        //满减
        subtract;

        private static Map<String, Promotion.Type> map = new HashMap<>();

        static {
            map.put("包邮", freeShipping);
            map.put("满减", subtract);
        }

        @JsonCreator
        public static Promotion.Type forValue(String value) {
            return map.get(value);
        }

        @JsonValue
        public String toValue() {
            for (Map.Entry<String, Promotion.Type> entry : map.entrySet()) {
                if (entry.getValue() == this) {
                    return entry.getKey();
                }
            }

            return "";
        }
    }

    /**
     * 促销类型
     */
    private Type type;

    /**
     * 名称
     */
    private String name;

    /**
     * 标题
     */
    private String title;

    /**
     * 起始日期
     */
    private Date beginDate;

    /**
     * 结束日期
     */
    private Date endDate;

    /**
     * 最小价格
     */
    private BigDecimal minimumPrice;

    /**
     * 最大价格
     */
    private BigDecimal maximumPrice;

    /**
     * 是否允许使用优惠券
     */
    private Boolean isCouponAllowed;

    /**
     * 是否启动
     */
    private Boolean isUsed;


    /**
     * 介绍
     */
    private String introduction;

    /**
     * 允许参加会员等级
     */
    private Set<MemberRank> memberRanks = new HashSet<MemberRank>();

    /**
     * 允许参与商品分类
     */
    private Set<ProductCategory> productCategories = new HashSet<ProductCategory>();

    /**
     * 允许参与商品
     */
    private Set<Product> products = new HashSet<Product>();

    /**
     * 允许参与品牌
     */
    private Set<Brand> brands = new HashSet<Brand>();

    /**
     * 赠送优惠券
     */
    private Set<Coupon> coupons = new HashSet<Coupon>();

    /**
     * 赠品
     */
    private List<GiftItem> giftItems = new ArrayList<GiftItem>();

    /**
     * 优惠价格
     */
    private BigDecimal cut;

    /**
     * 获取优惠价格
     *
     * @return 优惠价格
     */
    public BigDecimal getCut() {
        return cut;
    }

    /**
     * 设置优惠价格
     *
     * @param cut 优惠价格
     */
    public void setCut(BigDecimal cut) {
        this.cut = cut;
    }

    /**
     * 获取促销类型
     *
     * @return 促销类型
     */
    public Type getType() {
        return type;
    }

    /**
     * 设置促销类型
     *
     * @param type 促销类型
     */
    public void setType(Type type) {
        this.type = type;
    }

    /**
     * 获取名称
     *
     * @return 名称
     */
    @JsonProperty
    @NotEmpty
    @Length(max = 200)
    @Column(nullable = false)
    public String getName() {
        return name;
    }

    /**
     * 设置名称
     *
     * @param name 名称
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取标题
     *
     * @return 标题
     */
    @JsonProperty
    @NotEmpty
    @Length(max = 200)
    @Column(nullable = false)
    public String getTitle() {
        return title;
    }

    /**
     * 设置标题
     *
     * @param title 标题
     */
    public void setTitle(String title) {
        this.title = title;
    }

    /**
     * 获取起始日期
     *
     * @return 起始日期
     */
    @JsonProperty
    public Date getBeginDate() {
        return beginDate;
    }

    /**
     * 设置起始日期
     *
     * @param beginDate 起始日期
     */
    public void setBeginDate(Date beginDate) {
        this.beginDate = beginDate;
    }

    /**
     * 获取结束日期
     *
     * @return 结束日期
     */
    @JsonProperty
    public Date getEndDate() {
        return endDate;
    }

    /**
     * 设置结束日期
     *
     * @param endDate 结束日期
     */
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }


    /**
     * 获取最小商品价格
     *
     * @return 最小商品价格
     */
    @JsonProperty
    @Min(0)
    @Digits(integer = 12, fraction = 3)
    @Column(precision = 21, scale = 2)
    public BigDecimal getMinimumPrice() {
        return minimumPrice;
    }

    /**
     * 设置最小商品价格
     *
     * @param minimumPrice 最小商品价格
     */
    public void setMinimumPrice(BigDecimal minimumPrice) {
        this.minimumPrice = minimumPrice;
    }

    /**
     * 获取最大商品价格
     *
     * @return 最大商品价格
     */
    @JsonProperty
    @Min(0)
    @Digits(integer = 12, fraction = 3)
    @Column(precision = 21, scale = 2)
    public BigDecimal getMaximumPrice() {
        return maximumPrice;
    }

    /**
     * 设置最大商品价格
     *
     * @param maximumPrice 最大商品价格
     */
    public void setMaximumPrice(BigDecimal maximumPrice) {
        this.maximumPrice = maximumPrice;
    }


    /**
     * 获取是否允许使用优惠券
     *
     * @return 是否允许使用优惠券
     */
    @JsonProperty
    @NotNull
    @Column(nullable = false)
    public Boolean getIsCouponAllowed() {
        return isCouponAllowed;
    }

    /**
     * 设置是否允许使用优惠券
     *
     * @param isCouponAllowed 是否允许使用优惠券
     */
    public void setIsCouponAllowed(Boolean isCouponAllowed) {
        this.isCouponAllowed = isCouponAllowed;
    }


    /**
     * 获取是否启动该优惠
     *
     * @return 是否允许使用优惠券
     */
    @JsonProperty
    @NotNull
    @Column(nullable = false)
    public Boolean getIsUsed() {
        return isUsed;
    }

    /**
     * 设置是否启动该优惠
     *
     * @param isUsed 是否是否启动该优惠
     */
    public void setIsUsed(Boolean isUsed) {
        this.isUsed = isUsed;
    }


    /**
     * 获取介绍
     *
     * @return 介绍
     */
    @Lob
    public String getIntroduction() {
        return introduction;
    }

    /**
     * 设置介绍
     *
     * @param introduction 介绍
     */
    public void setIntroduction(String introduction) {
        this.introduction = introduction;
    }

    /**
     * 获取允许参加会员等级
     *
     * @return 允许参加会员等级
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "xx_promotion_member_rank")
    public Set<MemberRank> getMemberRanks() {
        return memberRanks;
    }

    /**
     * 设置允许参加会员等级
     *
     * @param memberRanks 允许参加会员等级
     */
    public void setMemberRanks(Set<MemberRank> memberRanks) {
        this.memberRanks = memberRanks;
    }

    /**
     * 获取允许参与商品分类
     *
     * @return 允许参与商品分类
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "xx_promotion_product_category")
    public Set<ProductCategory> getProductCategories() {
        return productCategories;
    }

    /**
     * 设置允许参与商品分类
     *
     * @param productCategories 允许参与商品分类
     */
    public void setProductCategories(Set<ProductCategory> productCategories) {
        this.productCategories = productCategories;
    }

    /**
     * 获取允许参与商品
     *
     * @return 允许参与商品
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "xx_promotion_product")
    public Set<Product> getProducts() {
        return products;
    }

    /**
     * 设置允许参与商品
     *
     * @param products 允许参与商品
     */
    public void setProducts(Set<Product> products) {
        this.products = products;
    }

    /**
     * 获取允许参与品牌
     *
     * @return 允许参与品牌
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "xx_promotion_brand")
    public Set<Brand> getBrands() {
        return brands;
    }

    /**
     * 设置允许参与品牌
     *
     * @param brands 允许参与品牌
     */
    public void setBrands(Set<Brand> brands) {
        this.brands = brands;
    }

    /**
     * 获取赠送优惠券
     *
     * @return 赠送优惠券
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "xx_promotion_coupon")
    public Set<Coupon> getCoupons() {
        return coupons;
    }

    /**
     * 设置赠送优惠券
     *
     * @param coupons 赠送优惠券
     */
    public void setCoupons(Set<Coupon> coupons) {
        this.coupons = coupons;
    }

    /**
     * 获取赠品
     *
     * @return 赠品
     */
    @Valid
    @OneToMany(mappedBy = "promotion", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    public List<GiftItem> getGiftItems() {
        return giftItems;
    }

    /**
     * 设置赠品
     *
     * @param giftItems 赠品
     */
    public void setGiftItems(List<GiftItem> giftItems) {
        this.giftItems = giftItems;
    }

    /**
     * 判断是否已开始
     *
     * @return 是否已开始
     */
    @Transient
    public boolean hasBegun() {
        return getBeginDate() == null || new Date().after(getBeginDate());
    }

    /**
     * 判断是否已结束
     *
     * @return 是否已结束
     */
    @Transient
    public boolean hasEnded() {
        return getEndDate() != null && new Date().after(getEndDate());
    }

    /**
     * 获取访问路径
     *
     * @return 访问路径
     */
    @Transient
    public String getPath() {
        if (getId() != null) {
            return PATH_PREFIX + "/" + getId() + PATH_SUFFIX;
        }
        return null;
    }

    @Transient
    public Set<Product> getAllProduct() {
        Set<Product> all = new HashSet<>();
        for (ProductCategory pc : productCategories) {
            all.addAll(pc.getProducts());
        }
        all.addAll(products);
        return all;
    }

}